/**
 * @brief	软定时器
 * @details	无
 * @par History:
 *	v1.7: 蔡正祥, 2024-03-24, 链表结构....\n
 *	v1.7: 蔡正祥, 2024-03-29, 修改了链表的初始化....\n
 *	v1.8: 蔡正祥, 2024-04-06, 增加Ti_obj_Get_Count....\n
 *	v1.9: 蔡正祥, 2024-04-23, 将malloc()去除，恢复数组结构\n
 *	v2.0: 蔡正祥, 2025-02-26, 重新优化了一下移植流程\n
 *	v2.1: 蔡正祥, 2025-06-23, 将Cycle的数据类型由uint16_t改成了uint32_t\n
 */
#ifndef __MY_TIMER_H
#define __MY_TIMER_H

#include "bsp_port.h"

#define TIM_TASK_MAX 10 // 最大定时任务数（默认可新建10个软定时对象，根据项目需求自行删减）

// 定时器可能的状态
typedef enum
{
        Ti_STOP,  // 停止
        Ti_RUN,   // 运行
        Ti_RESET, // 重置
} Ti_State;

// 软定时器
typedef struct
{
        uint32_t nowTimer;   // 此刻的时间
        uint32_t agoTimer;   // 之前的时间
        uint32_t Cycle;      // 周期
        int16_t RepeatCount; // 重复的次数 n<=0 : 无限;  n>0: 剩余的 时间     默认n=0
        uint16_t LeftCount;  // 剩余次数  默认n=0
        Ti_State State;      // 定时器可能的状态 暂停 恢复 重置   默认暂停
        void (*event)(void); // 定时要执行的函数
} bsp_TIM_t;

// #error 请进行下方 软定时器 移植工作 (阅读后请注释)
/************************************* 移   植  工  作  STM32G0 ************************************************/
#if 1
// 步骤1
#if 0
放到main.c文件中定时器初始化部分
LL_TIM_EnableCounter(TIMx);   // 使能计数
LL_TIM_EnableIT_UPDATE(TIMx); // 使能更新中断
LL_TIM_EnableAllOutputs(TIMx);
#endif
// 步骤2
#if 0
放在定时器中断中
// #include "bsp_Timer.h" //放置头文件
if (LL_TIM_IsActiveFlag_UPDATE(TIMx) == SET)
{
  bsp_Ti_IRQHandler();
}
LL_TIM_ClearFlag_UPDATE(TIMx); // 清除中断标志位
#endif
// 步骤3
void bsp_Ti_IRQHandler(void); // 定时中断函数,需要放到硬件1ms定时器里

// 步骤4
// #include "bsp_Timer.h" //放置头文件
void bsp_Ti_All_Handle(void); // 定时任务处理函数，放到程序主循环里
// 步骤5
#if 0
// void bsp_Ti_Debug(void); // 调试函数，用于快速进行调试，验证是否移植成功
bsp_TIM_t Ti_RUN_LED;
/*  @brief  定时任务调试程序
    @return 无
    @property 调试时用
*/
void bsp_Ti_Debug(void)
{
  Ti_obj_New(&Ti_RUN_LED, 500, Ti_RUN, Ti_RUN_LED_event);

  while (1)
  {
    bsp_Ti_All_Handle();
  }
}
#endif

#endif
/******************************************* 外 部 调 用 API ******************************************************/
/*  @brief  新建一个定时器对象
    @param  cycle
            定时周期
    @param  en
            是否运行    Ti_RUN运行 Ti_STOP停止
    @param  void (*event)(void)
            需要 定时执行的函数
    @return 无
    @property 无
*/
uint8_t Ti_obj_New(bsp_TIM_t *obj, uint32_t cycle, Ti_State en, void (*function)(void)); // 新建一个定时器对象
/*  @brief  定时器对象 停止
    @param  *obj
            对象
    @return 无
    @property 无
*/
void Ti_obj_Set_Stop(bsp_TIM_t *obj); // 定时器对象 停止
/*  @brief  定时器对象 运行
    @param  *obj
            对象
    @return 无
    @property 无
*/
void Ti_obj_Set_Run(bsp_TIM_t *obj); // 定时器对象 运行
/*  @brief  定时器对象 重置
    @param  *obj
            对象
    @return 无
    @property 重置后会重新计数并运行
*/
void Ti_obj_Set_Reset(bsp_TIM_t *obj); // 定时器对象 重置
/*  @brief  设置目标定时器对象的重复 次数
    @param  *obj
            对象
    @param  value
            需要重复的值
    @return 无
    @property 不设置默认无限循环
*/
void Ti_obj_Set_Count(bsp_TIM_t *obj, uint16_t value); // 设置目标定时器对象的重复次数
/*  @brief  重新设置定时器对象的 周期
    @param  *obj
            对象
    @param  value
            值 单位ms
    @return 无
    @property 定时器在创建时有个周期，通过这个函数可以更改周期
*/
void Ti_obj_Set_Cycle(bsp_TIM_t *obj, uint32_t value); // 重新设置定时器对象的周期
/*  @brief  设置定时对象的 事件
    @param  *obj
            对象
    @param  void (*event)(void)
            需要定时执行的事件
    @return 无
    @property 无
*/
void Ti_obj_Set_event(bsp_TIM_t *obj, void (*event)(void)); // 设置定时对象的事件
/*  @brief  获取目标定时器对象的剩余次数
    @param  *obj
            对象
    @return 运行剩余次数
    @property 无
*/
uint16_t Ti_obj_Get_Count(bsp_TIM_t *obj); // 获取目标定时器对象的剩余次数
/*  @brief  获取定时器对象运行状态
    @param  *obj
            定时器对象
    @return 无
    @property 无
*/
Ti_State Ti_obj_Get_State(bsp_TIM_t *obj); // 获取定时器对象运行状态
/*  @brief  销毁定时器对象
    @param  *obj
            要销毁的定时器
    @return 无
    @property 无
*/
void Ti_Obj_Delete(bsp_TIM_t *obj); // 删除定时器对象（慎用！）
/*  @brief  设置延时时间
    @param  msValue
            延时时间ms
    @return 无
    @property 无
*/
void bsp_Ti_Set_mDelay(uint32_t msValue); // 设置延时时间
/*  @brief  获取延时时间
    @return 无
    @property 无
*/
uint32_t bsp_Ti_Get_mDelay(void); // 获取延时时间
/*  @brief  暂停延时
    @return 无
    @property 无
*/
void bsp_Ti_mDelay_Pause(void); // 暂停延时
/*  @brief  恢复延时
    @return 无
    @property 无
*/
void bsp_Ti_mDelay_Renew(void); // 恢复延时

#endif

/*****************************************************************************************************************/
